/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2024 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "DeskLamp.h"
#include "oled.h"
#include "gui.h"
#include "ultrasonic.h"
#include "adc.h"
#include <string.h>
#include "esp_01.h"
#include "usart.h"
#include "ws2812_pwm_dma.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef union
{
    uint8_t value;
    struct
    {
        uint8_t KEY1 : 1;
        uint8_t KEY2 : 1;
        uint8_t KEY3 : 1;
        uint8_t KEY4 : 1;
        uint8_t KEY5 : 1;
        uint8_t KEY6 : 1;
    } bit;
} Key_Union;

typedef enum
{
    KEY_TYPE = 1,
    LIGHT_TYPE,
    COLOR_TYPE,
    ULTRA_TYPE,
    TIME_TYPE,
    MODE_TYPE,
    MAN_TYPE,
    VOICE_TYPE
} MSES_TYPE;

typedef struct
{
    MSES_TYPE type;
    uint32_t value;
    float value_f;
} Display_Message_TyD;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
QueueHandle_t DisplayQueue;
QueueHandle_t OperateQueue;
QueueHandle_t WiFiBufQueue;
extern uint8_t COM_ReadBuff[COM_UART_BUFFSIZE];
extern uint16_t uartCnt;

/* USER CODE END Variables */
osThreadId userHandle;
osThreadId desklampHandle;
osThreadId ultrasonicHandle;
osThreadId displayHandle;
osThreadId DeviceHandle;
osThreadId esp_01Handle;
osThreadId esp_recvHandle;
osThreadId TimeManagerHandle;
osSemaphoreId UpdataFlagHandle;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void user_thread(void const * argument);
void desklamp_thread(void const * argument);
void ultrasonic_thread(void const * argument);
void display_thread(void const * argument);
void device_thread(void const * argument);
void esp_01_thread(void const * argument);
void esp_recv_thread(void const * argument);
void Time_Manager(void const * argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* GetTimerTaskMemory prototype (linked to static allocation support) */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{
    *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
    *ppxIdleTaskStackBuffer = &xIdleStack[0];
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
    /* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */

/* USER CODE BEGIN GET_TIMER_TASK_MEMORY */
static StaticTask_t xTimerTaskTCBBuffer;
static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH];

void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize)
{
    *ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer;
    *ppxTimerTaskStackBuffer = &xTimerStack[0];
    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
    /* place for user code */
}
/* USER CODE END GET_TIMER_TASK_MEMORY */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
    /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* Create the semaphores(s) */
  /* definition and creation of UpdataFlag */
  osSemaphoreDef(UpdataFlag);
  UpdataFlagHandle = osSemaphoreCreate(osSemaphore(UpdataFlag), 1);

  /* USER CODE BEGIN RTOS_SEMAPHORES */
    /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
    /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
    /* add queues, ... */
    WiFiBufQueue = xQueueCreate(WIFI_BUFFER_NUM, sizeof(ESP_Buf_TyP *));
    DisplayQueue = xQueueCreate(20, sizeof(Display_Message_TyD));
    OperateQueue = xQueueCreate(20, sizeof(Display_Message_TyD));
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of user */
  osThreadDef(user, user_thread, osPriorityIdle, 0, 128);
  userHandle = osThreadCreate(osThread(user), NULL);

  /* definition and creation of desklamp */
  osThreadDef(desklamp, desklamp_thread, osPriorityBelowNormal, 0, 128);
  desklampHandle = osThreadCreate(osThread(desklamp), NULL);

  /* definition and creation of ultrasonic */
  osThreadDef(ultrasonic, ultrasonic_thread, osPriorityNormal, 0, 128);
  ultrasonicHandle = osThreadCreate(osThread(ultrasonic), NULL);

  /* definition and creation of display */
  osThreadDef(display, display_thread, osPriorityHigh, 0, 128);
  displayHandle = osThreadCreate(osThread(display), NULL);

  /* definition and creation of Device */
  osThreadDef(Device, device_thread, osPriorityNormal, 0, 150);
  DeviceHandle = osThreadCreate(osThread(Device), NULL);

  /* definition and creation of esp_01 */
  osThreadDef(esp_01, esp_01_thread, osPriorityAboveNormal, 0, 400);
  esp_01Handle = osThreadCreate(osThread(esp_01), NULL);

  /* definition and creation of esp_recv */
  osThreadDef(esp_recv, esp_recv_thread, osPriorityHigh, 0, 400);
  esp_recvHandle = osThreadCreate(osThread(esp_recv), NULL);

  /* definition and creation of TimeManager */
  osThreadDef(TimeManager, Time_Manager, osPriorityNormal, 0, 128);
  TimeManagerHandle = osThreadCreate(osThread(TimeManager), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
    /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_user_thread */
/**
 * @brief  Function implementing the user thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_user_thread */
void user_thread(void const * argument)
{
  /* USER CODE BEGIN user_thread */
    uint8_t SeekUserSpaceCnt = 0;
    UBaseType_t uxHighWaterMark = 0;

    printf("user thread init. \r\n");

    /* Infinite loop */
    for (;;)
    {
        HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);

        Set_Led_color(COLOR_WHITE);
        osDelay(500);
        Set_Led_color(COLOR_YELLOW);
        osDelay(500);
        Set_Led_color(COLOR_RED);
        osDelay(500);
        Set_Led_close();
        osDelay(500);
        Set_Led_open();

        if (SeekUserSpaceCnt++ > 5)
        {
            SeekUserSpaceCnt = 0;

            printf("\r\n-------------------------> Thread monitoring <------------------------- \r\n");
            uxHighWaterMark = uxTaskGetStackHighWaterMark(userHandle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "user_thread", 128 - uxHighWaterMark, uxHighWaterMark);
            uxHighWaterMark = uxTaskGetStackHighWaterMark(desklampHandle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "desklamp_thread", 128 - uxHighWaterMark, uxHighWaterMark);
            uxHighWaterMark = uxTaskGetStackHighWaterMark(ultrasonicHandle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "ultrasonic_thread", 128 - uxHighWaterMark, uxHighWaterMark);
            uxHighWaterMark = uxTaskGetStackHighWaterMark(displayHandle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "display_thread", 128 - uxHighWaterMark, uxHighWaterMark);
            uxHighWaterMark = uxTaskGetStackHighWaterMark(DeviceHandle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "device_thread", 256 - uxHighWaterMark, uxHighWaterMark);
            uxHighWaterMark = uxTaskGetStackHighWaterMark(esp_01Handle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "esp_01_thread", 256 - uxHighWaterMark, uxHighWaterMark);
            uxHighWaterMark = uxTaskGetStackHighWaterMark(esp_recvHandle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "esp_recv_thread", 256 - uxHighWaterMark, uxHighWaterMark);
            uxHighWaterMark = uxTaskGetStackHighWaterMark(TimeManagerHandle);
            printf("-----> Task: %s, use: %d, remain: %d \r\n", "Time_Manager", 128 - uxHighWaterMark, uxHighWaterMark);
            printf("\r\n\r\n");
        }
        osDelay(500);
    }
  /* USER CODE END user_thread */
}

/* USER CODE BEGIN Header_desklamp_thread */
/**
 * @brief Function implementing the desklamp thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_desklamp_thread */
void desklamp_thread(void const * argument)
{
  /* USER CODE BEGIN desklamp_thread */
    Display_Message_TyD ReadMessage;
    Key_Union key_value = {0};

    DeskLamp_Init();

    /* Infinite loop */
    for (;;)
    {

        xQueueReceive(DisplayQueue, &ReadMessage, portMAX_DELAY);

        /* 3种模式 */
/* -------------------------------------------------------MODE_AUTO--------------------------------------------------------------- */
        if (deviceUpReport.mode == MODE_AUTO)
        {
            switch (ReadMessage.type)
            {
            case KEY_TYPE:
                key_value.value = (uint8_t)ReadMessage.value;
                if (key_value.bit.KEY1 == 0)
                {
                    deviceUpReport.mode = MODE_MANUAL;
                }
                if (key_value.bit.KEY2 == 0)
                {
                    deviceUpReport.Color = (deviceUpReport.Color == COLOR_RED) ? (deviceUpReport.Color + 1) : (COLOR_WHITE);
                    /* Set LED color */
                    Set_Led_color(deviceUpReport.Color);
                }
                if (key_value.bit.KEY5 == 0)
                {
                    LongSittingReminder += 1000;
                }
                if (key_value.bit.KEY6 == 0)
                {
                    LongSittingReminder = (LongSittingReminder <= 1000) ? (0) : (LongSittingReminder - 1000);
                }

                break;

            case LIGHT_TYPE:
                deviceUpReport.brightness = (uint8_t)ReadMessage.value;
                /* Set brightness */
                Set_Led_color(deviceUpReport.Color);
                break;

            case ULTRA_TYPE:
                if ((deviceUpReport.Ultra > 120) && (deviceUpReport.LED_State == 1))
                {
                    deviceUpReport.LED_State = 0;
                    /* Close LED */
                    Set_Led_close();
                    deviceUpReport.RecordSitTime = HAL_GetTick();
                    HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
                }

                break;

            case MAN_TYPE:
                if ((ReadMessage.value == 1) && (deviceUpReport.Ultra < 60) && (deviceUpReport.LED_State != 1))
                {
                    deviceUpReport.LED_State = 1;
                    /* Open LED */
                    Set_Led_open();
                    deviceUpReport.RecordSitTime = HAL_GetTick();
                    HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
                }
                else if ((ReadMessage.value == 1) && (deviceUpReport.Ultra > 60) && (deviceUpReport.LED_State == 1))
                {
                    deviceUpReport.LED_State = 0;
                    /* Close LED */
                    Set_Led_close();
                    deviceUpReport.RecordSitTime = HAL_GetTick();
                    HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
                }

                break;

            default:
                break;
            }
        }
/* -------------------------------------------------------MODE_MANUAL--------------------------------------------------------------- */
        else if (deviceUpReport.mode == MODE_MANUAL)
        {
            switch (ReadMessage.type)
            {
            case KEY_TYPE:
                key_value.value = (uint8_t)ReadMessage.value;
                if (key_value.bit.KEY1 == 0)
                {
                    deviceUpReport.mode = MODE_NIGHT;
                }
                if (key_value.bit.KEY2 == 0)
                {
                    deviceUpReport.Color = (deviceUpReport.Color == COLOR_RED) ? (deviceUpReport.Color + 1) : (COLOR_WHITE);
                    /* Set LED color */
                    Set_Led_color(deviceUpReport.Color);
                }
                if ((key_value.bit.KEY3 == 0) && (key_value.bit.KEY4 == 0))
                {
                    if (deviceUpReport.LED_State == 0)
                    {
                        deviceUpReport.LED_State = 1;
                        /* Open LED */
                        Set_Led_open();
                        deviceUpReport.RecordSitTime = HAL_GetTick();
                        HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
                    }
                    else
                    {
                        deviceUpReport.LED_State = 0;
                        /* Close LED */
                        Set_Led_close();
                        deviceUpReport.RecordSitTime = HAL_GetTick();
                        HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
                    }
                }
                if (key_value.bit.KEY3 == 0)
                {
                    deviceUpReport.brightness = (deviceUpReport.brightness != 100) ? (deviceUpReport.brightness + 5) : (100);
                    /* Set brightness */
                    Set_Led_color(deviceUpReport.Color);
                }
                if (key_value.bit.KEY4 == 0)
                {
                    deviceUpReport.brightness = (deviceUpReport.brightness <= 5) ? (5) : (deviceUpReport.brightness - 5);
                    /* Set brightness */
                    Set_Led_color(deviceUpReport.Color);
                }
                if (key_value.bit.KEY5 == 0)
                {
                    LongSittingReminder += 1000;
                }
                if (key_value.bit.KEY6 == 0)
                {
                    LongSittingReminder = (LongSittingReminder <= 1000) ? (0) : (LongSittingReminder - 1000);
                }

                break;

            default:
                break;
            }
        }

/* -------------------------------------------------------MODE_NIGHT--------------------------------------------------------------- */
        else if (deviceUpReport.mode == MODE_NIGHT)
        {
            switch (ReadMessage.type)
            {
            case KEY_TYPE:
                key_value.value = (uint8_t)ReadMessage.value;
                if (key_value.bit.KEY1 == 0)
                {
                    deviceUpReport.mode = MODE_AUTO;
                }
                if (key_value.bit.KEY2 == 0)
                {
                    deviceUpReport.Color = (deviceUpReport.Color == COLOR_RED) ? (deviceUpReport.Color + 1) : (COLOR_WHITE);
                    /* Set LED color */
                    Set_Led_color(deviceUpReport.Color);
                }
                if (key_value.bit.KEY5 == 0)
                {
                    LongSittingReminder += 1000;
                }
                if (key_value.bit.KEY6 == 0)
                {
                    LongSittingReminder = (LongSittingReminder <= 1000) ? (0) : (LongSittingReminder - 1000);
                }

                break;

            case LIGHT_TYPE:
                deviceUpReport.brightness = ReadMessage.value;
                /* Set brightness */
                Set_Led_color(deviceUpReport.Color);
                break;

            case MAN_TYPE:
            case VOICE_TYPE:
                if ((ReadMessage.value == 1) && (deviceUpReport.LED_State != 1))
                {
                    deviceUpReport.LED_State = 1;
                    /* Open LED */
                    Set_Led_open();
                    deviceUpReport.RecordSitTime = HAL_GetTick();
                    HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
                }

                break;

            default:
                break;
            }
        }


    }
  /* USER CODE END desklamp_thread */
}

/* USER CODE BEGIN Header_ultrasonic_thread */
/**
 * @brief Function implementing the ultrasonic thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_ultrasonic_thread */
void ultrasonic_thread(void const * argument)
{
  /* USER CODE BEGIN ultrasonic_thread */
    Display_Message_TyD ultrasonic_message = {.type = ULTRA_TYPE};
    float last_ult_value = 0;

    Ultrasonic_Init();

    /* Infinite loop */
    for (;;)
    {
        /* 临界区测距 */
        taskENTER_CRITICAL();
        Ultrasonic_Task();
        taskEXIT_CRITICAL();
        if (Ultrasonic_GetUpdataState(0) == UTS_UPDATA)
        {
            if (last_ult_value != Ultrasonic_GetDisCm(0))
            {
                // printf("Ultrasonic: %.2fcm \r\n", Ultrasonic_GetDisCm(0));
                ultrasonic_message.value_f = last_ult_value = (float)Ultrasonic_GetUpdataDisCm(0);
                deviceUpReport.Ultra = last_ult_value;
                xQueueSend(DisplayQueue, &ultrasonic_message, 0);
            }
        }
        else
        {
            if (last_ult_value != 400.0)
            {
                ultrasonic_message.value_f = last_ult_value = 400.0;
                deviceUpReport.Ultra = last_ult_value;
                xQueueSend(DisplayQueue, &ultrasonic_message, 0);
            }
        }
        osDelay(150);
    }
  /* USER CODE END ultrasonic_thread */
}

/* USER CODE BEGIN Header_display_thread */
/**
 * @brief Function implementing the display thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_display_thread */
void display_thread(void const * argument)
{
  /* USER CODE BEGIN display_thread */
    Display_Message_TyD ReadMessage;
    char Display_str[50] = {0};

    OLED_Init();

    // GUI_ShowString(0, 0, "Test", 16, 1);
    // OLED_Display();

    /* Infinite loop */
    for (;;)
    {
        xQueueReceive(DisplayQueue, &ReadMessage, portMAX_DELAY);
        xQueueSend(OperateQueue, &ReadMessage, 0);
        memset(Display_str, 0, sizeof(Display_str));
        switch (ReadMessage.type)
        {
        case TIME_TYPE:
            sprintf(Display_str, "--%2d:%2d:%2d--", deviceUpReport.time_h, deviceUpReport.time_m, deviceUpReport.time_s);
            GUI_ShowString(0, 0, "               ", 16, 1);
            GUI_ShowString(16, 0, (uint8_t *)Display_str, 16, 1);
            break;

        case COLOR_TYPE:
            GUI_FillRectangle(0, 16, 127, 31, 0);
            GUI_ShowString(30, 16, "W", 16, 1);
            GUI_ShowString(60, 16, "Y", 16, 1);
            GUI_ShowString(90, 16, "R", 16, 1);
            switch (ReadMessage.value)
            {
            case 0:
                GUI_FillRectangle(24, 16, 44, 31, 1);
                GUI_ShowString(30, 16, "W", 16, 0);
                break;
            case 1:
                GUI_FillRectangle(54, 16, 74, 31, 1);
                GUI_ShowString(60, 16, "Y", 16, 0);
                break;
            case 2:
                GUI_FillRectangle(84, 16, 104, 31, 1);
                GUI_ShowString(90, 16, "R", 16, 0);
                break;

            default:
                break;
            }
            break;

        case LIGHT_TYPE:
            GUI_FillRectangle(0, 34, 127, 45, 0);
            GUI_DrawRectangle(0, 34, 127, 45, 1);
            GUI_FillRectangle(0, 34, (uint8_t)(127.0 * (ReadMessage.value / 100.0)), 45, 1);
            break;

        case ULTRA_TYPE:

            break;

        case MODE_TYPE:
            GUI_FillRectangle(0, 48, 127, 63, 0);
            GUI_ShowString(30, 48, "A", 16, 1);
            GUI_ShowString(60, 48, "M", 16, 1);
            GUI_ShowString(90, 48, "N", 16, 1);
            switch (ReadMessage.value)
            {
            case 0:
                GUI_FillRectangle(24, 48, 44, 63, 1);
                GUI_ShowString(30, 48, "A", 16, 0);
                break;
            case 1:
                GUI_FillRectangle(54, 48, 74, 63, 1);
                GUI_ShowString(60, 48, "M", 16, 0);
                break;
            case 2:
                GUI_FillRectangle(84, 48, 104, 63, 1);
                GUI_ShowString(90, 48, "N", 16, 0);
                break;

            default:
                break;
            }
            break;

        default:
            break;
        }

        OLED_Display();
    }
  /* USER CODE END display_thread */
}

/* USER CODE BEGIN Header_device_thread */
/**
 * @brief Function implementing the Device thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_device_thread */
void device_thread(void const * argument)
{
  /* USER CODE BEGIN device_thread */
    /* Send the message to Display thread message. */
    Display_Message_TyD Device_message;
    /* LED */
    uint16_t ADC1_Buffer[10] = {0};
    uint16_t ADC1_BufCnt = sizeof(ADC1_Buffer) / sizeof(ADC1_Buffer[0]);
    uint32_t Light_Adc = 0, Vrefint_Adc = 0, Last_Light_Adc = 0;
    /* Key */
    Key_Union Key;
    /* color */
    Device_message.type = COLOR_TYPE;
    Device_message.value = deviceUpReport.Color;
    xQueueSend(DisplayQueue, &Device_message, 0);
    /* mode */
    Device_message.type = MODE_TYPE;
    Device_message.value = deviceUpReport.mode;
    xQueueSend(DisplayQueue, &Device_message, 0);
    /* Ultrasonic */
    float last_ult_value = 0;

    /* ADC Start . */
    HAL_ADCEx_Calibration_Start(&hadc1);
    HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC1_Buffer, ADC1_BufCnt);
    /* Infinite loop */
    for (;;)
    {
        /* 光强度获取 */
        /* ADC滤波 */
        Light_Adc = 0;
        Vrefint_Adc = 0;
        for (size_t i = 0; i < ADC1_BufCnt; i++)
        {
            if ((i % 2) == 0)
            {
                Light_Adc += ADC1_Buffer[i];
            }
            else if ((i % 2) == 1)
            {
                Vrefint_Adc += ADC1_Buffer[i];
            }
        }
        // printf("Light_Adc: %d, Vrefint_Adc: %d  %d\r\n", Light_Adc, Vrefint_Adc, deviceUpReport.mode);
        Light_Adc = Light_Adc / (ADC1_BufCnt / 2);
        Vrefint_Adc = Vrefint_Adc / (ADC1_BufCnt / 2);
        /* 声音传感器状态获取 */

        /* 人体红外传感器状态获取 */

        /* 键值获取 */
        Key.bit.KEY1 = HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);
        Key.bit.KEY2 = HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin);
        Key.bit.KEY3 = HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin);
        Key.bit.KEY4 = HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin);
        Key.bit.KEY5 = HAL_GPIO_ReadPin(KEY5_GPIO_Port, KEY5_Pin);
        Key.bit.KEY6 = HAL_GPIO_ReadPin(KEY6_GPIO_Port, KEY6_Pin);

        /* 发送键值 */
        Device_message.type = KEY_TYPE;
        Device_message.value = Key.value;
        xQueueSend(DisplayQueue, &Device_message, 0);

        if (deviceUpReport.mode == 35)
        {
            printf("mode: %d\r\n", deviceUpReport.mode);
            deviceUpReport.mode = MODE_AUTO;
        }

        if (deviceUpReport.mode == MODE_AUTO)
        {
            /* 发送亮度 */
            if (Last_Light_Adc != Light_Adc)
            {
                Last_Light_Adc = Light_Adc;
                Device_message.type = LIGHT_TYPE;
                deviceUpReport.brightness = (uint8_t)((1 - (Light_Adc / 4096.0)) * 100); /* 计算亮度百分百 */
                Device_message.value = deviceUpReport.brightness;
                xQueueSend(DisplayQueue, &Device_message, 0);
            }
            /* 发送声音传感器状态 */

            /* 发送人体红外传感器状态 */

            /* 发送超声波测距值 */

        }
        else if (deviceUpReport.mode == MODE_MANUAL)
        {
            /* 发送超声波测距值 */
            Device_message.type = ULTRA_TYPE;
            if (Ultrasonic_GetUpdataState(0) == UTS_UPDATA)
            {
                if (last_ult_value != Ultrasonic_GetDisCm(0))
                {
                    printf("Ultrasonic: %.2fcm \r\n", Ultrasonic_GetDisCm(0));
                    Device_message.value_f = deviceUpReport.Ultra = last_ult_value = (float)Ultrasonic_GetUpdataDisCm(0);
                    xQueueSend(DisplayQueue, &Device_message, 0);
                }
            }
            else
            {
                if (last_ult_value != 400.0)
                {
                    Device_message.value_f = deviceUpReport.Ultra = last_ult_value = 400.0;
                    xQueueSend(DisplayQueue, &Device_message, 0);
                }
            }
        }
        else if (deviceUpReport.mode == MODE_NIGHT)
        {
            /* 发送亮度 */
            if (Last_Light_Adc != Light_Adc)
            {
                Last_Light_Adc = Light_Adc;
                Device_message.type = LIGHT_TYPE;
                Device_message.value = deviceUpReport.brightness = (uint32_t)((1 - (Light_Adc / 4096.0)) * 100); /* 计算亮度百分百 */
                xQueueSend(DisplayQueue, &Device_message, 0);
            }
            /* 发送声音传感器状态 */
        }

        osDelay(150);
    }
  /* USER CODE END device_thread */
}

/* USER CODE BEGIN Header_esp_01_thread */
/**
 * @brief Function implementing the esp_01 thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_esp_01_thread */
void esp_01_thread(void const * argument)
{
  /* USER CODE BEGIN esp_01_thread */
    osDelay(2000);
    /* Infinite loop */
    for (;;)
    {
        Esp_01_Task();
        osDelay(1000);
    }
  /* USER CODE END esp_01_thread */
}

/* USER CODE BEGIN Header_esp_recv_thread */
/**
 * @brief Function implementing the esp_recv thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_esp_recv_thread */
void esp_recv_thread(void const * argument)
{
  /* USER CODE BEGIN esp_recv_thread */
    ESP_Buf_TyP *EspRxBuf = NULL;

    /* Infinite loop */
    for (;;)
    {
        if (xQueueReceive(WiFiBufQueue, &EspRxBuf, portMAX_DELAY) == pdTRUE)
        {
            Esp_01_RecvHandle(EspRxBuf->buf, EspRxBuf->size);
            // HAL_UART_Transmit(&huart1, EspRxBuf->buf, EspRxBuf->size, 100);
            memset(EspRxBuf->buf, 0, EspRxBuf->size);
            EspRxBuf->UseFlag = 0;
        }
    }
  /* USER CODE END esp_recv_thread */
}

/* USER CODE BEGIN Header_Time_Manager */
/**
 * @brief Function implementing the TimeManager thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_Time_Manager */
void Time_Manager(void const * argument)
{
  /* USER CODE BEGIN Time_Manager */
    Display_Message_TyD timeMessage = {.type = TIME_TYPE};
    uint32_t Time_Manager_Tick = osKernelSysTick();
    printf("Time_Manager_Tick: %d \r\n", Time_Manager_Tick);

    /* Infinite loop */
    for (;;)
    {
        /* Monitor sedentary */
        if (deviceUpReport.LED_State == 1)
        {
            if ((HAL_GetTick() - deviceUpReport.RecordSitTime) >= LongSittingReminder)
            {
                HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
            }
        }
        else
        {
            deviceUpReport.RecordSitTime = HAL_GetTick();
            HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
        }

        xQueueSend(DisplayQueue, &timeMessage, NULL);
        osDelayUntil(&Time_Manager_Tick, 1000);
    }
  /* USER CODE END Time_Manager */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

